home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianDialogs.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  19KB  |  691 lines

  1. /*    ScianDialogs.c
  2.     creates and manages simple dialog windows for scian
  3.  
  4.     Jim Lyons
  5.     10/12/90
  6.  
  7.     4/10/91 added error alerts
  8.     4/27/91 added Ask alert
  9.     5/4/91    added Choose alert
  10.     5/29/91 EMP removed library headers
  11.     7/10/91 made Choose buttons dynamically sized
  12.     7/17/91 changed Ask callback method
  13.     7/19/91 changed names of Ask and Choose to AskUser and AlertUser
  14.     9/6/91    made AskUser and AlertUser return window pointer
  15.     10/14/91 added help strings to buttons
  16.     10/25/91 made deferred task routine to close dialog windows
  17.     6/1/92  EMP fixed DismissError not to use DoClose
  18.     6/13/92 EMP changed to use method declarations, not prototypes
  19. */
  20.  
  21. #include "Scian.h"
  22. #include "ScianStyle.h"
  23. #include "ScianFontSystem.h"
  24. #include "ScianTypes.h"
  25. #include "ScianIDs.h"
  26. #include "ScianArrays.h"
  27. #include "ScianWindows.h"
  28. #include "ScianDraw.h"
  29. #include "ScianTextBoxes.h"
  30. #include "ScianObjWindows.h"
  31. #include "ScianColors.h"
  32. #include "ScianControls.h"
  33. #include "ScianButtons.h"
  34. #include "ScianLists.h"
  35. #include "ScianEvents.h"
  36. #include "ScianTimers.h"
  37. #include "ScianErrors.h"
  38. #include "ScianDialogs.h"
  39. #include "ScianTitleBoxes.h"
  40. #include "ScianScripts.h"
  41.  
  42. /* EMP static method declarations */
  43.  
  44. static ObjPtr DrawAlertPanel();
  45. static ObjPtr PressAlertPanel();
  46. static ObjPtr DismissError();
  47. static ObjPtr DoRevert();
  48. static ObjPtr DoCancel();
  49. static ObjPtr DoOK();
  50. static ObjPtr DoEnter();
  51. static ObjPtr CheckForEnter();
  52. static ObjPtr AlertResponse();
  53. static ObjPtr PrevError();
  54. static ObjPtr NextError();
  55.  
  56. /* static function prototypes */
  57. #ifdef PROTO
  58.  
  59. static void PopDialog(void);
  60. static void DrawBorder(int , int );
  61.  
  62. #else
  63.  
  64. static void PopDialog();
  65. static void DrawBorder();
  66.  
  67. #endif
  68.  
  69. extern WinInfoPtr allWindows;
  70.  
  71. ObjPtr    dialogClass, errAlertStuff;
  72.  
  73. /*** parts stuff ***/
  74. ObjPtr    partsClass;
  75.  
  76. /* globals used by PopDialog and Ask and Choose callbacks */
  77. static FuncTyp CallbackFunction = NULL;
  78. static WinInfoPtr theDlg1 = NULL, theDlg2 = NULL;
  79. static int btnNumber;
  80. static ObjPtr theReply = NULL;
  81.  
  82. void InitDialogs()
  83. {
  84.     dialogClass = NewObject(objWindowClass, 0);
  85.         AddToReferenceList(dialogClass);
  86.     SetVar(dialogClass, NAME, NewString("Dialog"));
  87.  
  88.     /* create dummy object to store parameters for the error alert.
  89.         ERRORLIST: list of errors not yet dismissed by user
  90.         ERRORNUMBER: currently displayed error message
  91.     */
  92.     errAlertStuff = NewObject(NULLOBJ, 0);
  93.     AddToReferenceList(errAlertStuff);
  94.     SetVar(errAlertStuff, NAME, NewString("Alert stuff"));
  95.     SetVar(errAlertStuff, ERRORLIST, NewList());
  96.     SetVar(errAlertStuff, ERRORNUMBER, NewInt(0));
  97.  
  98.     partsClass = NewObject(NULLOBJ, 0);
  99.     AddToReferenceList(partsClass);
  100.     SetVar(partsClass, NAME, NewString("Parts"));
  101. }
  102.  
  103. void KillDialogs()
  104. /*Kills the dialog windows */
  105. {
  106.     DeleteThing(dialogClass);
  107.     DeleteThing(errAlertStuff);
  108.     DeleteThing(partsClass);
  109. }
  110.  
  111. /*************************************************************************** PARTS */
  112.  
  113. #ifdef PROTO
  114. ObjPtr NewAlertPanel(int left, int right, int bottom, int top, char *name)
  115. #else
  116. ObjPtr NewAlertPanel(left, right, bottom, top, name)
  117. int left, right, bottom, top;
  118. char *name;
  119. #endif
  120. {
  121.     ObjPtr retVal;
  122.  
  123.     retVal = NewObject(partsClass, 0);
  124.     if (retVal)
  125.     {
  126.         SetVar(retVal, NAME, NewString(name));
  127.         Set2DIntBounds(retVal, left, right, bottom, top);
  128.         SetMethod(retVal, DRAW, DrawAlertPanel);
  129.         SetMethod(retVal, PRESS, PressAlertPanel);
  130.         return retVal;
  131.     }
  132.      else return NULLOBJ;
  133. }
  134.  
  135. static ObjPtr DrawAlertPanel(thePanel)
  136. ObjPtr thePanel;
  137. {
  138. #ifdef GRAPHICS
  139.     ObjPtr theColor;
  140.     int left, right, bottom, top;
  141.     int color;
  142.  
  143.     Get2DIntBounds(thePanel, &left, &right, &bottom, &top);
  144.  
  145.     if (theColor = GetVar(thePanel, COLOR)) color = GetInt(theColor);
  146.     else color = UIINFOALERT;
  147.  
  148.     /* draw the outside edge */
  149.     DrawRaisedEdge(left+1, right-1, bottom+1, top-1);
  150.  
  151.     /* draw the color border */
  152.     FrameUIWideRect(left+EDGE+1, right-EDGE-1, bottom+EDGE+1, top-EDGE-1, ALERTBORDER, color);
  153.  
  154.     /* draw the inside edge */
  155.     DrawSunkenEdge(left+ALERTBORDER+EDGE, right-ALERTBORDER-EDGE,
  156.             bottom+ALERTBORDER+EDGE, top-ALERTBORDER-EDGE);
  157.  
  158.     /* draw the surface */
  159.     FillUIRect(left+ALERTBORDER+2*EDGE, right-ALERTBORDER-2*EDGE,
  160.             bottom+ALERTBORDER+2*EDGE, top-ALERTBORDER-2*EDGE, UIALERTBG);
  161.  
  162.     /* draw the panel outline */
  163.     FrameUIRect(left, right, bottom, top, UIBLACK);
  164. #endif
  165.     return NULLOBJ;
  166. }
  167.  
  168. static ObjPtr PressAlertPanel(thePanel, mouseX, mouseY, flags)
  169. ObjPtr thePanel;
  170. int mouseX, mouseY;
  171. long flags;
  172. {
  173. #ifdef INTERACTIVE
  174.     int left, right, bottom, top;
  175.  
  176.     Get2DIntBounds(thePanel, &left, &right, &bottom, &top);
  177.  
  178.     /* return if mouse outside panel */
  179.     if (mouseX < left || mouseX > right || mouseY < bottom 
  180.             || mouseY > top) return ObjFalse;
  181.  
  182.     /* pop dialog window */
  183.     if (theDlg1 = (WinInfoPtr) GetVar(GetVar(thePanel, PARENT), PARENT))
  184.     {
  185.         DoTask(PopDialog);
  186.     }
  187.  
  188.     /* do help if active */
  189.     if (TOOL(flags) == T_HELP)
  190.     {
  191.         ContextHelp(thePanel);
  192.         return ObjTrue;
  193.     }
  194. #endif
  195.     /* "pass" press to contents */
  196.     return ObjFalse;
  197. }
  198.  
  199. static void PopDialog(void) /* deferred task to pop dialog window */
  200. {
  201.     if (theDlg1)
  202.     {
  203.         PopWindow(theDlg1);
  204.     }
  205.     theDlg1 = NULL;
  206. }
  207.  
  208. ObjPtr MakeDialogName(dialog)
  209. ObjPtr dialog;
  210. /*Makes a dialog's name*/
  211. {
  212.     ObjPtr repObj;
  213.     ObjPtr var;
  214.  
  215.     repObj = GetVar(dialog, OWNERWINDOW);
  216.     if (repObj)
  217.     {
  218.     var = GetVar(repObj, NAME);
  219.     SetVar(dialog, NAME, var);
  220.     if (var)
  221.     {
  222.         SetWindowTitle(dialog, GetString(var));
  223.     }
  224.     }
  225.  
  226.     return ObjTrue;
  227. }
  228.  
  229.  
  230. /**************************************************************************** GET DIALOG */
  231. #ifdef PROTO
  232. WinInfoPtr GetDialog(WinInfoPtr owner, ObjPtr object, char *title, 
  233.     int minWidth, int minHeight, int maxWidth, int maxHeight, long flags)
  234. #else
  235. WinInfoPtr GetDialog(owner, object, title, minWidth, minHeight, maxWidth, maxHeight, flags)
  236. WinInfoPtr owner;
  237. ObjPtr object;
  238. char *title;
  239. int minWidth, minHeight, maxWidth, maxHeight;
  240. long flags;
  241. #endif
  242. /*    Returns ptr to dialog with owner owner associated with object object if it
  243.     already exists, else calls NewOpened to make one.  
  244. */
  245. {
  246.     WinInfoPtr retVal;
  247.  
  248.     /* first see if this dialog already exists */
  249.     if ( retVal = DialogExists(owner, object) )
  250.     {
  251.         PopWindow(retVal);
  252.     }
  253.     else
  254.     {
  255.         retVal = NewObjWindow(dialogClass, title, flags, minWidth,
  256.                     minHeight, maxWidth, maxHeight);
  257.         SetVar((ObjPtr) retVal, CONTENTS, NewList());
  258.         SetVar((ObjPtr) retVal, OWNERWINDOW, (ObjPtr) owner);
  259.         SetVar((ObjPtr) retVal, WHICHDIALOG, object);
  260.         SetVar((ObjPtr) retVal, CLASSID, NewInt(CLASS_DIALOG));
  261.  
  262.         if (owner)
  263.         {
  264.             /*Stuff to make name change automatically*/
  265.             SetVar((ObjPtr) retVal, NAME, NewString(title));
  266.             DeclareDependency((ObjPtr) retVal, NAME, OWNERWINDOW);
  267.             DeclareIndirectDependency((ObjPtr) retVal, NAME, OWNERWINDOW, NAME);
  268.             SetMethod((ObjPtr) retVal, NAME, MakeDialogName);
  269.         }
  270.     }
  271.     return retVal;    
  272. }
  273.  
  274. WinInfoPtr DialogExists(owner, object)
  275. WinInfoPtr owner;
  276. ObjPtr object;
  277. /*    determine if a dialog already exists with owner owner 
  278.     and associated object object. If so return its pointer, else NULL. 
  279. */
  280. {
  281.     WinInfoPtr w;
  282.  
  283.     w = allWindows;
  284.     while (w)
  285.     {
  286.         if (IsDialog((ObjPtr) w))
  287.         {
  288.             if(GetVar((ObjPtr) w, OWNERWINDOW) == (ObjPtr) owner 
  289.                     && Eql(GetVar((ObjPtr) w, WHICHDIALOG), object))
  290.                 return w;
  291.         }
  292.         w = w->next;
  293.     }
  294.     return (WinInfoPtr) 0;
  295. }
  296.  
  297.  
  298. /************************************************************************* REPORT ERROR */
  299. #ifdef PROTO
  300. ObjPtr ReportError(char *name, char *text)
  301. #else
  302. ObjPtr ReportError(name, text)
  303. char *name, *text;
  304. #endif
  305. {
  306.     char errMsg[256];
  307.  
  308.     if (logging)
  309.     {
  310.         sprintf(errMsg, "# Error in %s: %s\n",name, text);
  311.         Log(errMsg);
  312.     }
  313.     fprintf(stderr,"Error in %s: %s\n",name, text);
  314.     return NULLOBJ;
  315. }
  316.  
  317.  
  318. /********************************************************************************* ASK */
  319. #ifdef PROTO
  320. WinInfoPtr AskUser(WinInfoPtr ownerWin, char *prompt, FuncTyp Callback, char *reply)
  321. #else
  322. WinInfoPtr AskUser(ownerWin, prompt, Callback, reply)
  323. WinInfoPtr ownerWin;
  324. char *prompt, *reply;
  325. FuncTyp Callback;
  326. #endif
  327. {
  328.     WinInfoPtr askDlg;
  329.     ObjPtr panel, alertPanel, contents, promptBox, replyBox, revertBtn, cancelBtn, okBtn;
  330.     ObjPtr thePrompt, obj;
  331.  
  332.     if (runningRemote) /* print prompt to stdout and get response now */
  333.     {
  334. #define MAXLINELENGTH 80
  335.         char chrbuf[MAXLINELENGTH], *nl;
  336.  
  337.         printf("\n***\n%s\n",prompt); /*** fix for multiline prompts? ***/
  338.         if (*reply) printf("(Default = %s)\n? ", reply);
  339.         else printf("? ");
  340.         fgets(chrbuf, MAXLINELENGTH, stdin);
  341.         if ( nl = strchr(chrbuf, '\n') ) *nl = '\0'; /* eliminate newline */
  342.         if (*chrbuf) Callback(ownerWin, chrbuf);
  343.         else Callback(ownerWin, reply); /* default */
  344.         return (WinInfoPtr) NULL;
  345.     }
  346.  
  347.     /* see if dialog exists */
  348.     thePrompt = NewString(prompt);
  349.     askDlg = GetDialog(ownerWin, thePrompt, "Ask",
  350.         ASKWIDTH, ASKHEIGHT, ASKWIDTH, ASKHEIGHT,
  351.         WINUI + WINFIXEDSIZE + WINNOFRAME + WINCENTERED);
  352.     if(!askDlg) return (WinInfoPtr) NULL;
  353.  
  354.     if (GetVar((ObjPtr) askDlg, REPOBJ)) /* dialog exists */
  355.     {
  356.         /* pop ask dialog */
  357.         PopWindow(askDlg);
  358.     }
  359.     else /* make the dialog box */
  360.     {
  361.         SetVar((ObjPtr) askDlg, REPOBJ, thePrompt);
  362.         contents = GetVar((ObjPtr) askDlg, CONTENTS); /* contents of window */
  363.  
  364.         /* put in panel */
  365.         panel = NewPanel(greyPanelClass, 0, ASKWIDTH, 0, ASKHEIGHT);
  366.         PrefixList(contents, panel);
  367.         SetVar(panel, PARENT, (ObjPtr) askDlg);
  368.  
  369.         contents = GetVar(panel, CONTENTS); /* contents of panel */
  370.  
  371.         /* put in pretty panel */
  372.         alertPanel = NewAlertPanel(0, ASKWIDTH, 0, ASKHEIGHT, "Ask Panel");
  373.         PrefixList(contents, alertPanel);
  374.         SetVar(alertPanel, PARENT, panel);
  375.  
  376.         /* put in prompt */
  377.         promptBox = NewTextBox(SIDEMARGIN, ASKWIDTH - SIDEMARGIN,
  378.                 ASKHEIGHT - TOPMARGIN - PROMPTHT, ASKHEIGHT - TOPMARGIN,
  379.                 PLAIN, "Prompt Box", prompt);
  380.         PrefixList(contents, promptBox);
  381.         SetVar(promptBox, PARENT, panel);
  382.         SetVar(promptBox, UIFONT, NewInt(PROMPTTEXTFONT));
  383.         SetTextColor(promptBox, PROMPTTEXTCOLOR);
  384.  
  385.         /* put in reply field */
  386.         replyBox = NewTextBox(SIDEMARGIN, ASKWIDTH - SIDEMARGIN,
  387.                 BOTMARGIN + OKBTNHT + INTERSPACE,
  388.                 BOTMARGIN + OKBTNHT + INTERSPACE + EDTEXTHT,
  389.                 EDITABLE + WITH_PIT + ONE_LINE, "Reply", reply);
  390.         PrefixList(contents, replyBox);
  391.         SetVar(replyBox, PARENT, panel);
  392.         SetVar(replyBox, DATA, NewString(reply)); /* ref to by DoRevert */
  393.         SetMethod(replyBox, CALLBACK, Callback); /* ref by DoEnter (via DoOK) */
  394.         SetMethod(replyBox, ENTERMETHOD, DoEnter);
  395.         SelectAll(replyBox);
  396.  
  397.         /* put in buttons */
  398.         if (*reply) /* put in Revert button only if given a default reply */
  399.         {
  400.             revertBtn = NewButton(SIDEMARGIN, SIDEMARGIN + OKBTNWID, 
  401.                     BOTMARGIN, BOTMARGIN + OKBTNHT, "Revert");
  402.             PrefixList(contents, revertBtn);
  403.             SetVar(revertBtn, PARENT, panel);
  404.             SetVar(revertBtn, REPOBJ, replyBox);
  405.             SetMethod(revertBtn, CHANGEDVALUE, DoRevert);
  406.             SetVar(revertBtn, HELPSTRING, NewString("Pressing this button \
  407. will undo all editing and restore the text to its original state without closing the \
  408. dialog window."));
  409.         }
  410.  
  411.         cancelBtn = NewButton(ASKWIDTH - SIDEMARGIN - 2*OKBTNWID - SMALLGAP,
  412.                 ASKWIDTH - SIDEMARGIN - OKBTNWID - SMALLGAP,
  413.                 BOTMARGIN, BOTMARGIN + OKBTNHT, "Cancel");
  414.         PrefixList(contents, cancelBtn);
  415.         SetVar(cancelBtn, PARENT, panel);
  416.         SetMethod(cancelBtn, CHANGEDVALUE, DoCancel);
  417.         SetVar(cancelBtn, HELPSTRING, NewString("Pressing this button \
  418. will cancel this dialog window without causing any other action."));
  419.         okBtn = NewButton(ASKWIDTH - SIDEMARGIN - OKBTNWID,
  420.                 ASKWIDTH - SIDEMARGIN,
  421.                 BOTMARGIN, BOTMARGIN + OKBTNHT, "OK");
  422.         PrefixList(contents, okBtn);
  423.         SetVar(okBtn, PARENT, panel);
  424.         SetMethod(okBtn, CHANGEDVALUE, DoOK);
  425.         SetVar(replyBox, BUTTON, okBtn); /* ref by DoEnter routine */
  426.         SetVar(okBtn, HELPSTRING, NewString("Pressing this button \
  427. will dismiss this dialog window and cause the indicated action to proceed."));
  428.  
  429.         /* put border around ok button to indicate default action */
  430.         obj = NewTitleBox(ASKWIDTH - SIDEMARGIN - OKBTNWID - EDGE,
  431.                 ASKWIDTH - SIDEMARGIN + EDGE - 1,
  432.                 BOTMARGIN - EDGE, BOTMARGIN + OKBTNHT + EDGE - 1, NIL);
  433.         PrefixList(contents, obj);
  434.         SetVar(obj, PARENT, panel);
  435.         
  436.         SetVar(okBtn, REPOBJ, replyBox);
  437.     }
  438.     return askDlg;
  439. }
  440.  
  441. static ObjPtr DoRevert(btn)
  442. ObjPtr btn;
  443. {
  444.     ObjPtr textBox;
  445.  
  446.     textBox = GetVar(btn, REPOBJ);
  447.     SetTextBox(textBox, GetString(GetVar(textBox, DATA)));
  448.     SelectAll(textBox);
  449.     return NULLOBJ;
  450. }
  451.  
  452. static ObjPtr DoCancel(btn)
  453. ObjPtr btn;
  454. {
  455.     theDlg2 = (WinInfoPtr) GetVar(GetVar(btn, PARENT), PARENT);
  456.     DeferMessage((ObjPtr) theDlg2, DISPOSE); /* close dialog... */
  457.     return NULLOBJ;
  458. }
  459.  
  460. static void AskCallback()
  461. {
  462.     if (!theReply)
  463.     {
  464.         ReportError("AskCallback", "No reply!");
  465.         return;
  466.     }
  467.     if (!CallbackFunction)
  468.     {
  469.         ReportError("AskCallback","No completion routine!");
  470.         return;
  471.     }
  472.     if (!theDlg1)
  473.     {
  474.         ReportError("AskCallback", "No owner window!");
  475.         return;
  476.     }
  477.     IdleAllWindows();
  478.     SelWindow(theDlg1);
  479.     (*CallbackFunction)(theDlg1, GetString(theReply));
  480.     theReply = NULL;
  481.     CallbackFunction = NULL;
  482.     theDlg1 = NULL;
  483. }
  484.  
  485. static ObjPtr DoOK(btn)
  486. ObjPtr btn;
  487. {
  488.     ObjPtr replyBox = GetVar(btn, REPOBJ);
  489.     CallbackFunction = GetMethod(replyBox, CALLBACK);
  490.     theReply = GetVar(replyBox, VALUE);
  491.     theDlg1 = theDlg2 = (WinInfoPtr) GetVar(GetVar(replyBox, PARENT), PARENT);
  492.     DeferMessage((ObjPtr) theDlg2, DISPOSE); /* close dialog... */
  493.     DoTask(AskCallback); /* ...then do completion routine */
  494.     return NULLOBJ;
  495. }
  496.  
  497. static ObjPtr DoEnter(replyBox)
  498. ObjPtr replyBox;
  499. {
  500.     ObjPtr btn;
  501.  
  502.     btn = GetVar(replyBox, BUTTON); /* dialog OK button */
  503.     SetValue(btn, ObjTrue);
  504.     return NULLOBJ;
  505. }
  506.  
  507. /************************************************************************** ALERT USER */
  508. #ifdef PROTO
  509. WinInfoPtr AlertUser(int level, WinInfoPtr owner, char *prompt, FuncTyp Callback,
  510.         int nBtns, ...)
  511. #else
  512. WinInfoPtr AlertUser(level, owner, prompt, Callback, nBtns, ...)
  513. int level;
  514. WinInfoPtr owner;
  515. char *prompt;
  516. FuncTyp Callback;
  517. int nBtns;
  518. #endif
  519. {
  520.     WinInfoPtr alertWin;
  521.     ObjPtr thePrompt;
  522.  
  523.     if (runningRemote) /* print prompt to stdout and get response now */
  524.     {
  525.         printf("\n***\n%s\n",prompt); /*** fix for multiline prompts? ***/
  526.         if (nBtns > 1) 
  527.         {
  528.             int i;
  529.             char **p, c[4];
  530.  
  531.             while (1)
  532.             {
  533.                 printf("\n  Enter number:\n");
  534.                 p = (char **)((&nBtns) + 1); /* point to first label */
  535.                 for (i=1; i<=nBtns; ++i) printf("  %d. %s\n", i, *(p+nBtns-i));
  536.                 printf("? ");
  537.                 fgets(c, 4, stdin);
  538.                 *c -= '0';
  539.                 if (*c < 1 || *c > nBtns) continue;
  540.                 if (Callback) Callback(owner, nBtns - *c);
  541.                 break;
  542.             }
  543.         }
  544.         return (WinInfoPtr) NULL;
  545.     }
  546.  
  547.     /* see if dialog exists */
  548.     thePrompt = NewString(prompt);
  549.     alertWin = GetDialog(owner, thePrompt, "Alert",
  550.         ALERTWIDTH, ALERTHEIGHT, ALERTWIDTH, ALERTHEIGHT,
  551.         WINUI + WINFIXEDSIZE + WINNOFRAME + WINCENTERED);
  552.     if(!alertWin) return (WinInfoPtr) NULL;
  553.  
  554.     if (GetVar((ObjPtr) alertWin, REPOBJ)) /* dialog exists */
  555.     {
  556.         /* pop alert */
  557.         PopWindow(alertWin);
  558.     }
  559.     else /* make the dialog box */
  560.     {
  561.         ObjPtr panel, alertPanel, contents, promptBox, btn, obj;
  562.         char **p;
  563.         int i, btnWid, nextPos,  defBtnLeft;
  564.  
  565.         SetVar((ObjPtr) alertWin, REPOBJ, thePrompt);
  566.         SetMethod((ObjPtr) alertWin, KEYDOWN, CheckForEnter);
  567.         SetMethod((ObjPtr) alertWin, DATA, Callback); /* save completion routine */
  568.         contents = GetVar((ObjPtr) alertWin, CONTENTS); /* contents of window */
  569.  
  570.         /* put in panel */
  571.         panel = NewPanel(greyPanelClass, 0, ALERTWIDTH, 0, ALERTHEIGHT);
  572.         PrefixList(contents, panel);
  573.         SetVar(panel, PARENT, (ObjPtr) alertWin);
  574.  
  575.         contents = GetVar(panel, CONTENTS); /* contents of panel */
  576.  
  577.         /* put in pretty panel */
  578.         alertPanel = NewAlertPanel(0, ALERTWIDTH, 0, ALERTHEIGHT, "Alert Panel");
  579.         PrefixList(contents, alertPanel);
  580.         SetVar(alertPanel, PARENT, panel);
  581.         SetVar(alertPanel, COLOR, NewInt(level));
  582.  
  583.         /* put in prompt */
  584.         promptBox = NewTextBox(SIDEMARGIN, ALERTWIDTH - SIDEMARGIN,
  585.                 BOTMARGIN + OKBTNHT + INTERSPACE, ALERTHEIGHT - TOPMARGIN,
  586.                 PLAIN, "Prompt Box", prompt);
  587.         PrefixList(contents, promptBox);
  588.         SetVar(promptBox, PARENT, panel);
  589.         SetVar(promptBox, UIFONT, NewInt(PROMPTTEXTFONT));
  590.  
  591.         /* put in the buttons */
  592.         p = (char **)((&nBtns) + 1); /* point to first button label parameter */
  593.         SetUIFont(BUTTONFONT);
  594.         if (nBtns <= 0) /* default to OK button only */
  595.         {
  596.             btn = NewButton((defBtnLeft = ALERTWIDTH - SIDEMARGIN - OKBTNWID), ALERTWIDTH - SIDEMARGIN,
  597.                     BOTMARGIN, BOTMARGIN + OKBTNHT, "OK");
  598.             PrefixList(contents, btn);
  599.             SetVar(btn, PARENT, panel);
  600.             /* if callback is NULL just cancel the dialog, else call the routine */
  601.             if (Callback)
  602.             {
  603.                 SetVar(btn, DATA, NewInt(0));
  604.                 SetMethod(btn, CHANGEDVALUE, AlertResponse);
  605.             }
  606.             else SetMethod(btn, CHANGEDVALUE, DoCancel);
  607.             SetVar(btn, REPOBJ, (ObjPtr) alertWin);
  608.         }
  609.         else
  610.         {
  611.             nextPos = ALERTWIDTH - SIDEMARGIN + SMALLGAP; /* set up for loop */
  612.             for (i=0; i<nBtns; ++i, ++p) /* from right to left; rightmost button is zero */
  613.             {
  614.                 btnWid = 2*BTNMARGIN + StrWidth(*p);
  615.                 btnWid = GRIDSIZE * (int) (btnWid/GRIDSIZE + 1); /* constrain to grid */ 
  616.                 nextPos = nextPos - SMALLGAP - btnWid;
  617.                 if (i == 0) defBtnLeft = nextPos; /* remeber default btn position */
  618.                 if (nextPos < SIDEMARGIN) break; /* not enough room */
  619.                 btn = NewButton(nextPos, nextPos + btnWid,
  620.                         BOTMARGIN, BOTMARGIN + OKBTNHT, *p);
  621.                 PrefixList(contents, btn);
  622.                 SetVar(btn, PARENT, panel);
  623.                 SetVar(btn, DATA, NewInt(i));
  624.                 SetMethod(btn, CHANGEDVALUE, AlertResponse);
  625.                 SetVar(btn, REPOBJ, (ObjPtr) alertWin);
  626.             }
  627.         }
  628.         /* put border around rightmost button to indicate default action */
  629.         obj = NewTitleBox(defBtnLeft - EDGE,
  630.                 ALERTWIDTH - SIDEMARGIN + EDGE - 1,
  631.                 BOTMARGIN - EDGE, BOTMARGIN + OKBTNHT + EDGE - 1, NIL);
  632.         PrefixList(contents, obj);
  633.         SetVar(obj, PARENT, panel);
  634.     }
  635.     return alertWin;
  636. }
  637.  
  638. static void AlertCallback()
  639. {
  640.     if (!CallbackFunction)
  641.     {
  642.         return;
  643.     }
  644.     IdleAllWindows();
  645. /***    SelWindow(theDlg1); this doesn't work ***/
  646.     (*CallbackFunction)(theDlg1, btnNumber);
  647.     CallbackFunction = NULL;
  648.     theDlg1 = NULL;
  649. }
  650.  
  651. static ObjPtr AlertResponse(btn)
  652. ObjPtr btn;
  653. {
  654.     WinInfoPtr repObj;
  655.  
  656.     btnNumber = GetInt(GetVar(btn, DATA)); /* button number, 0 is rightmost */
  657.  
  658.     repObj = (WinInfoPtr) GetVar(btn, REPOBJ); /* the alert dialog */
  659.     theDlg2 = repObj; /* save for close task */
  660.     theDlg1 = (WinInfoPtr) GetVar((ObjPtr) repObj, OWNERWINDOW); /* save for cpl rtn */
  661.  
  662.     CallbackFunction = GetMethod((ObjPtr) repObj, DATA); /* save completion routine */
  663.  
  664.     DeferMessage((ObjPtr) theDlg2, DISPOSE); /* close dialog... */
  665.     DoTask(AlertCallback); /* ...then do completion routine */
  666.     return ObjTrue;
  667. }
  668.  
  669. static ObjPtr CheckForEnter(dlg, key, flags)
  670. ObjPtr dlg; /* really a WinInfoPtr but who cares */
  671. int key;
  672. long flags;
  673. {
  674.     if (key == '\r')
  675.     {
  676.     btnNumber = 0; /* default button */
  677.     theDlg2 = (WinInfoPtr) dlg; /* save for close task */
  678.     theDlg1 = (WinInfoPtr) GetVar(dlg, OWNERWINDOW); /* save for cpl rtn */
  679.  
  680.     CallbackFunction = GetMethod(dlg, DATA); /* save completion routine */
  681.  
  682.     DeferMessage((ObjPtr) theDlg2, DISPOSE); /* close dialog... */
  683.     DoTask(AlertCallback); /* ...then do completion routine */
  684.     return ObjTrue;
  685.     }
  686.     else
  687.     {
  688.     return ObjFalse;
  689.     }
  690. }
  691.